package com.example.synchost5.aop;

import com.example.synchost5.entity.ResponseData;
import com.example.synchost5.exception.GlobalException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

import static com.example.synchost5.entity.ResponseStatusEnum.*;

/**
 * 此版本的切面执行顺序为:
 * around begin
 * before
 * afterReturning / afterThrowing
 * after
 * around end
 */
@SuppressWarnings("unused")
@Aspect
@Component
public class ControllerAdvice {

    private static final Logger logger = LoggerFactory.getLogger(ControllerAdvice.class);

    /**
     * 全局
     */
    @Pointcut("execution(* com.example.synchost5.controller.*.*(..))")
    public void universal() {}

    /**
     * 要排除的
     */
    @Pointcut("execution(* com.example.synchost5.controller.SyncHostController.getHost(..))")
    public void except() {}

    /**
     * 包装返回结果为统一格式
     * @param joinPoint 所有 controller
     * @return ResponseData
     */
    @Around("universal() && !except()")
    public ResponseData around(ProceedingJoinPoint joinPoint) {
        logger.info("Around start.");
        Map<String, Object> resultMap = new HashMap<>();
        try {
            Object result = joinPoint.proceed();
            resultMap.put("result", result);
        } catch (GlobalException e) {
            return new ResponseData(BUSINESS_ERROR, e.getErrorMap(), new HashMap<>());
        } catch (Throwable e) {
            e.printStackTrace();
            return new ResponseData(SERVER_ERROR, new HashMap<>(), resultMap);
        } finally {
            logger.info("Around end.");
        }

        return new ResponseData(OK, null, resultMap);
    }
}
